/**
 *  Copyright 2013 University Pierre & Marie Curie - UMR CNRS 7606 (LIP6/MoVe)
 *  All rights reserved.   This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  Initial contributor:
 *    Lom M. Hillah - <lom-messan.hillah@lip6.fr>
 *
 *  Mailing list:
 *    lom-messan.hillah@lip6.fr
 */
package fr.lip6.msr4j.asf.datamodel;

import java.util.HashSet;
import java.util.Set;

/**
 * Apache Software Foundation Committer model.
 * 
 * @author lom
 * 
 */
public final class ASFCommitter {

	private static final double HALF = 0.5;

	/**
	 * The committer SVN Id
	 */
	private final String svnId;
	/**
	 * The committer's name
	 */
	private final String name;
	/**
	 * Is the committer a member of the ASF?
	 */
	private boolean isASFMember;

	/**
	 * Is the committer an emeritus member of the ASF?
	 */
	private boolean isEmeritusMember;
	/**
	 * Has this committer signed the Contributor License Agreement?
	 */
	private boolean hasSignedCLA;
	/**
	 * Committer's email
	 */
	private String email;

	/**
	 * Committer's web site at ASF
	 */
	private String webSite;
	/**
	 * SVN Projects this committer is involved in.
	 */
	private Set<SVNProject> projects;
	/**
	 * Other committers in all projects this committer is involved in.
	 */
	private Set<ASFCommitter> workWith;

	public ASFCommitter(String id, String name) {
		this.svnId = id;
		this.name = name;
		projects = new HashSet<SVNProject>();
		workWith = new HashSet<ASFCommitter>();
	}

	public boolean isApacheMember() {
		return isASFMember;
	}

	public void setApacheMember(boolean isApacheMember) {
		this.isASFMember = isApacheMember;
	}

	public boolean isHasSignedCLA() {
		return hasSignedCLA;
	}

	public void setHasSignedCLA(boolean hasSignedCLA) {
		this.hasSignedCLA = hasSignedCLA;
	}

	public Set<SVNProject> getProjects() {
		return projects;
	}

	public void setProjects(Set<SVNProject> projects) {
		this.projects = projects;
	}

	public boolean addProject(SVNProject p) {
		this.workWith.addAll(p.getCommitters());
		p.addCommitter(this);
		return this.projects.add(p);
	}

	public boolean hasProject(SVNProject p) {
		return this.projects.contains(p);
	}

	public String getName() {
		return name;
	}

	public String getSvnId() {
		return svnId;
	}

	/**
	 * New colleague for this committer on a common project.
	 * 
	 * @param c
	 * @return true if unknown before (now a colleague), false otherwise
	 */
	public boolean addColleague(ASFCommitter c) {
		return this.workWith.add(c);
	}

	public Set<ASFCommitter> getColleagues() {
		return this.workWith;
	}

	/**
	 * How many connections (projects and collaborators)?
	 * 
	 * @return the number of connections to projects this committer is involved
	 *         in + the number of collaborators he is linked to on these
	 *         projects.
	 */
	public int degree() {
		return this.projects.size() + this.workWith.size();
	}

	/**
	 * Rough weight of this committer as his degreee * 2 if he is a member of
	 * ASF, his degree only otherwise.
	 * 
	 * @return the supposed weight of this committer among committers
	 */
	public double weight() {
		return (isASFMember ? this.degree() / HALF : this.degree());
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((svnId == null) ? 0 : svnId.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		ASFCommitter other = (ASFCommitter) obj;
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		if (svnId == null) {
			if (other.svnId != null) {
				return false;
			}
		} else if (!svnId.equals(other.svnId)) {
			return false;
		}
		return true;
	}

	@Override
	public String toString() {
		return "ASFCommitter [svnId=" + svnId + ", name=" + name
				+ ", isASFMember=" + isASFMember + ", isEmeritusMember="
				+ isEmeritusMember + ", hasSignedCLA=" + hasSignedCLA
				+ ", webSite=" + webSite + "]";
	}

	public boolean isEmeritusMember() {
		return isEmeritusMember;
	}

	public void setEmeritusMember(boolean isEmeritusMember) {
		this.isEmeritusMember = isEmeritusMember;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getWebSite() {
		return webSite;
	}

	public void setWebSite(String webSite) {
		this.webSite = webSite;
	}
}
